package com.nowcoder.community.service;

import com.nowcoder.community.dao.AlphaDao;
import com.nowcoder.community.dao.DiscussPostMapper;
import com.nowcoder.community.dao.UserMapper;
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.util.CommunityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Date;

@Service    // 容器管理 业务Bean
@Scope      // "prototype" 设置容器内Bean 不是单例  // 默认单例
@Slf4j(topic = "AlphaService.class")
public class AlphaService {

    @Autowired
    private AlphaDao alphaDao;

    @Autowired
    private DiscussPostMapper discussPostMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TransactionTemplate transactionTemplate;

    public String find() {
        return alphaDao.select();
    }

    public AlphaService() {
        System.out.println("实例化AlphaService");
    }

    @PostConstruct      // 让Spring容器管理 该方法 并且在构造器之后调用
    public void init() {
        System.out.println("初始化AlphaService");
    }

    @PreDestroy         // 让Spring容器管理 该方法 且在销毁该对象之前调用
    public void destroy() {
        System.out.println("销毁AlphaService");
    }

    // REQUIRED：支持当前事务(外部事物),如果外部事务不存在 则创建新的事务
    // REQUIRES_NEW：创建一个新事物、并且暂停当前事务(外部事物)
    // NESTED：如果当前存在A事务(外部事物)，则嵌套在该A事务中执行(B事务 独立的提交和回滚 否则与REQUIRED一样)
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public Object save1() {

        // 先增加用户
        User user = User.builder()
                .username("alpha")
                .salt(CommunityUtil.generateUUID().substring(0, 5))
                .email("alpha@qq.com")
                .headerUrl("http://image.nowcoder.com99t.png")
                .createTime(new Date())
                .build();
        user.setPassword(CommunityUtil.md5(user.getSalt() + "123"));
        userMapper.insertUser(user);

        // 再增加帖子
        DiscussPost discussPost = DiscussPost.builder()
                .userId(user.getId())
                .title("Hello")
                .content("新人报到!!!")
                .createTime(new Date())
                .build();
        discussPostMapper.insertDiscussPost(discussPost);

        Integer.valueOf("abc");

        return "ok";
    }

    public Object save2() {
        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        return transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                // 先增加用户
                User user = User.builder()
                        .username("beta")
                        .salt(CommunityUtil.generateUUID().substring(0, 5))
                        .email("beta@qq.com")
                        .headerUrl("http://image.nowcoder.com99t.png")
                        .createTime(new Date())
                        .build();
                user.setPassword(CommunityUtil.md5(user.getSalt() + "123"));
                userMapper.insertUser(user);

                // 再增加帖子
                DiscussPost discussPost = DiscussPost.builder()
                        .userId(user.getId())
                        .title("你好")
                        .content("我是新人!!!")
                        .createTime(new Date())
                        .build();
                discussPostMapper.insertDiscussPost(discussPost);

                Integer.valueOf("abc");

                return "ok";
            }
        });
    }

    @Async    // 让该方法在多线程环境下 被异步的调用
    public void execute1() {
        log.warn("execute1");
    }

    // @Scheduled(initialDelay = 10000, fixedDelay = 1000)    // 让该方法在多线程环境下 被异步的定时的调用
    public void execute2() {
        log.warn("execute2");
    }


}
